using System.Collections.Generic;

namespace Test.ConsoleProgram.Algorithm.Solution
{
    [TestDescription("算法: 0224. 基本计算器")]
    public class No0224_Calculate : AbsBaseTestItem
    {
        /*
        实现一个基本的计算器来计算一个简单的字符串表达式 s 的值。
        示例 1：
            输入：s = "1 + 1"
            输出：2
        示例 2：
            输入：s = " 2-1 + 2 "
            输出：3
        示例 3：
            输入：s = "(1+(4+5+2)-3)+(6+8)"
            输出：23
        提示：
            1 <= s.length <= 3 * 105
            s 由数字、'+'、'-'、'('、')'、和 ' ' 组成
            s 表示一个有效的表达式
        */

        public override void OnTest()
        {
            Assert.TestExe(Calculate, "1 + 1", 2);
            Assert.TestExe(Calculate, " 2-1 + 2 ", 3);
            Assert.TestExe(Calculate, "(1+(4+5+2)-3)+(6+8)", 23);
        }

        public int Calculate(string s)
        {
            Stack<int> ops = new Stack<int>();
            ops.Push(1);
            int sign = 1, ret = 0, n = s.Length, i = 0;
            while (i < n)
            {
                char c = s[i];
                if (c == ' ')
                {
                    i++;
                    continue;
                }
                if (c == '+')
                {
                    sign = ops.Peek();
                    i++;
                    continue;
                }
                if (c == '-')
                {
                    sign = -ops.Peek();
                    i++;
                    continue;
                }
                if (c == '(')
                {
                    ops.Push(sign);
                    i++;
                    continue;
                }
                if (c == ')')
                {
                    ops.Pop();
                    i++;
                    continue;
                }
                int num = 0;
                while (i < n && char.IsNumber(s[i]))
                {
                    c = s[i];
                    num = num * 10 + (c - '0');
                    i++;
                }
                ret += sign * num;
            }
            return ret;
        }
    }
}
